# -*- coding: utf-8 -*-
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
import psycopg2
import sys
from dlgAttachmentsImpl import *
from metadataobject import *
from qgisFeaturesEditorUtil import *

# initialize Qt resources from file resouces.py
import resources

class PostMeta:

  def __init__(self, iface):
    self.metaSuffix = "_meta" #TODO move meta suffix to config
    # save reference to the QGIS interface
    self.iface = iface
    self.layer = None
    self.feature = None
    self.metaTableName = None

  def initGui(self):
    # create action that will start plugin configuration
    self.action = QAction(QIcon(":/plugins/postmeta/icons/attach.png"), "PostMeta plugin", self.iface.mainWindow())
    self.action.setWhatsThis("Configuration for test plugin")
    self.action.setStatusTip("This is status tip")
    self.action.setEnabled(False)
    QObject.connect(self.action, SIGNAL("triggered()"), self.run)

    # add toolbar button and menu item
    self.iface.addToolBarIcon(self.action)
    self.iface.addPluginToMenu("&PostMeta", self.action)

    QObject.connect(self.iface, SIGNAL("currentLayerChanged ( QgsMapLayer *)"), self.currentLayerChanged)

    # Setup for attachments dialogl
    self.dlgAttachments = DlgAttachmentsImpl()

  def unload(self):
    # remove the plugin menu item and icon
    self.iface.removePluginMenu("&PostMeta plugin",self.action)
    self.iface.removeToolBarIcon(self.action)

    QObject.disconnect(self.iface, SIGNAL("currentLayerChanged ( QgsMapLayer *)"), self.currentLayerChanged)

  def run(self):
    self.conn_string = getConectionStringFromLayer(self.layer)
    qgsDataSourceUri = getDataSourceUriFromLayer(self.layer)
    try:
      if None != qgsDataSourceUri:
        self.dbShema = qgsDataSourceUri.schema()
        self.keyColumn = qgsDataSourceUri.keyColumn()
        if None == self.dbShema or "" == self.dbShema:
          self.dbShema = "public"
        # get a connection, if a connect cannot be made an exception will be raised here
        conn = psycopg2.connect(self.conn_string)
        metaTableName = str(qgsDataSourceUri.table()+self.metaSuffix)
        # conn.cursor will return a cursor object, you can use this cursor to perform queries
        cursor = conn.cursor()
        selectMetaStr = str("select count(*) from pg_tables where schemaname='" +
        self.dbShema + "' and tablename='" +
        metaTableName + "'")
        print "looking for metatables: " + selectMetaStr
        cursor.execute(selectMetaStr)
        result=cursor.fetchone()
        print "Found metatables: " + str(result[0])
        if(1 > result[0]):
          self.createMetaTable(qgsDataSourceUri.table(), conn)
          conn.commit()
        self.metaTableName = metaTableName
        self.showMetaDialog()
    except:
      # Get the most recent exception
      exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
      # Exit the script and print an error telling what happened.
      print "Database connection failed!\n ->%s" % (exceptionValue)
    finally:
      cursor.close()
      conn.close()

  def currentLayerChanged (self, layer):
    '''Enable or disable plugin button depending on current layer selection '''
    self.action.setEnabled(False)
    if None != self.layer:
       QObject.disconnect(self.layer, SIGNAL("selectionChanged()"), self.layerSelectionChanged)
    self.layer = None
    if None != layer:
      if 0 == layer.type():
        if "PostgreSQL database with PostGIS extension" == layer.dataProvider().storageType():
          self.layer=layer
          QObject.connect(self.layer, SIGNAL("selectionChanged()"), self.layerSelectionChanged)

  def layerSelectionChanged(self):
    '''Handler for selection of any feature on the layer'''
    if self.layer.selectedFeatureCount() == 1: # Attachments allowed only for one feature at time
      self.action.setEnabled(True)
      self.feature = self.layer.selectedFeatures()[0]
    else:
      self.action.setEnabled(False)

  def showMetaDialog(self):
    '''Function to show metaeditor dialog'''
    if None != self.dlgAttachments:
      self.dlgAttachments.setModal(True)
      self.dlgAttachments.setConnectionString(self.conn_string)
      self.dlgAttachments.setMetaTableName(self.dbShema + "." + self.metaTableName)
      self.dlgAttachments.setFeature(self.feature)
      self.dlgAttachments.show()

  def createMetaTable(self, tableName, connection):
    '''Creates metatable for given table within given connection'''
    try:
      curr=connection.cursor()
      targetTableName = self.dbShema + "." + tableName
      targetPrefix = tableName
      sqlCreateTable='''
      CREATE TABLE {0}{1}
      (
        mid serial,
        tag character varying(255), -- Tag used to identify what kind of meta stored in the datafield: attachment, description, etc
        mimetype character varying(255), -- Mime type of the data in the datafield
        meta character varying(255), -- Additional info about data stored in the datafield
        data bytea, -- Metadata assotiated with object
        fk_obj bigint NOT NULL,
        CONSTRAINT {3}{1}_pk PRIMARY KEY (mid),
        CONSTRAINT {3}{1}_fk_obj_fkey FOREIGN KEY (fk_obj)
            REFERENCES {0} ({2}) MATCH SIMPLE
            ON UPDATE CASCADE 
            ON DELETE CASCADE
      )
      WITH OIDS;
      '''.format(targetTableName,self.metaSuffix, self.keyColumn, targetPrefix)
      curr.execute(sqlCreateTable)
      
    except:
      QMessageBox.critical(None, "Error", "Can't create attachments table")
      # Get the most recent exception
      exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
      print "Error on table creation!\n ->%s" % (exceptionValue)
      raise
    finally:
      curr.close()
